package main

import (
	"bytes"
	"io"
	"io/ioutil"
	"net/http"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/gin-gonic/gin/binding"
	"github.com/go-playground/validator/v10"
)


func main()  {
	r := gin.Default()

	//===============================
	//请求路由
	//get 返回json
	r.GET("/ping", func(c *gin.Context) {
		c.JSON(200,gin.H{
			"code":200,
			"msg":"ok!!!",
		})
	})
	//get 返回字符串
	r.GET("/hello", func(c *gin.Context) {
		c.String(200,"hello!!!")
	})
	//any 请求方法
	r.Any("any",func(c *gin.Context) {
		c.JSON(200,gin.H{
			"code":200,
			"msg":"any ok",
		})
	})

	//加载静态文件的两种方式
	// r.Static("/static","./static")
	r.StaticFS("/static",http.Dir("static"))
	
	//请求路由泛绑定
	//URL为/info/sdsds等会全部打到该路由上
	r.GET("/info/*info",func(c *gin.Context) {
		c.String(200,"user info")
	})


	//===============================
	//获取请求参数
	//获取get请求URL参数
	r.GET("/user/:name/:password",func(c *gin.Context) {
		c.JSON(http.StatusOK,gin.H{
			"name":c.Param("name"),
			"password":c.Param("password"),
		})
	})

	//获取get请求参数 /test?first=han&second=kai
	r.GET("/test",func(c *gin.Context) {
		first := c.Query("first")
		second := c.Query("second")
		c.JSON(http.StatusOK,gin.H{
			"first_name":first,
			"last_name":second,
		})
	})

	//获取post请求参数 
	r.POST("/test",func(c *gin.Context) {
	bodyBytes,err:=ioutil.ReadAll(c.Request.Body)
	if err != nil {
		c.String(http.StatusBadRequest,err.Error())
		c.Abort()
	}
	c.Request.Body = io.NopCloser(bytes.NewBuffer(bodyBytes))
	first := c.PostForm("first")
	second := c.PostForm("second")
	c.JSON(http.StatusOK,gin.H{
		"first_name":first,
		"last_name":second,
	})
	})

	//获取bind参数，绑定到结构体
	r.GET("/testin",personfunc)
	r.POST("/testin",personfunc)


	//===============================
	//验证请求参数
	//结构体验证
	//如上 获取bind参数

	//自定义验证规则
	if v,ok := binding.Validator.Engine().(*validator.Validate);ok{
		v.RegisterValidation("bookabledate",bookableDate)
	}
	r.GET("/bookable",func(c *gin.Context) {
		var b Booking
		if err:= c.ShouldBind(&b);err!=nil{
			c.JSON(500,gin.H{"err":err.Error()})
			return
		}
		c.JSON(200,gin.H{
			"msg":"ok",
			"booking":b,
		})
	})

	//启动
	r.Run()
}


type Person struct{
	Name string `json:"name" form:"name" binding:"required"`
	Address string `json:"address" form:"address" binding:"required"`
	Gender string `json:"gender" form:"gender" binding:"required"`
	Age int8 `json:"age" form:"age" binding:"required,gt=10"`
}
func personfunc(c *gin.Context)  {
	var p Person
	if err:=c.ShouldBind(&p);err!=nil{
		c.String(200,"err:%v",err)
		c.Abort() //结束程序
		return //返回
	}else{
		c.JSON(http.StatusOK,gin.H{
			"name":p.Name,
			"address":p.Address,
			"gender":p.Gender,
			"age":p.Age,
		})
	}
}


type Booking struct{
	CheckIn time.Time `form:"check_in" binding:"required,bookabledate" time_format:"2006-01-02"`
	CheckOut time.Time `form:"check_out" binding:"required,gtfield=CheckIn" time_format:"2006-01-02"`
}
var bookableDate validator.Func =func (fl validator.FieldLevel) bool {
	data,ok := fl.Field().Interface().(time.Time)
	if ok{
		today := time.Now()
		if today.After(data){
			return false
		}
	}
	return true
}
